// ignore_for_file: depend_on_referenced_packages

library;

import 'dart:io';
import 'dart:math';

import 'package:external_path_ios_mac/external_path_ios_mac.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_saver/src/tools/extensions/files_extensions.dart';
import 'package:flutter_saver/src/tools/extensions/string_extensions.dart';
import 'package:http/http.dart' as http;
import 'package:native_android_path/native_android_path.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';

export 'package:external_path_ios_mac/external_path_ios_mac.dart';
// export 'package:flutter_saver/src/tools/extensions/permissions_request.dart';
export 'package:path/path.dart';

//// A package to save images and files to the downloads folder.
///
/// Example:
/// ```dart
/// import 'package:flutter_saver/flutter_saver.dart';
///
/// await FlutterSaver.saveImageWindowsWeb(
///   fileImage: fileImage,
///   fileName: 'example',
///   type: 'jpg',
/// );
/// ```
class FlutterSaver {
  static String? savefilePath;

  /// Saves an image file to the downloads folder for Windows or Web.
  ///
  /// Parameters:
  /// - [fileImage]: The image file to be saved.
  /// - [lengthFileName]: The length of the randomly generated file name (default is 5).
  /// - [fileName]: Optional custom file name.
  /// - [type]: The file extension/type (default is 'jpg').
  ///
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  static Future<bool> saveImageWindowsWeb({
    required File? fileImage,
    int lengthFileName = 5,
    String? fileName,
    String? type = 'jpg',
  }) async {
    String filePath = '';
    String localFileName =
        "image_${StringExtension.randomFileName(lengthFileName)}";

    String finalFilename = fileName ?? localFileName;

    try {
      if (kIsWeb || Platform.isWindows) {
        Directory? downloadDirectoryWindows = await getDownloadsDirectory();
        filePath = '${downloadDirectoryWindows!.path}/$finalFilename.$type';
        debugPrint("defaultPath: $filePath");
      } else {
        throw Exception('Error saving image: $e');
      }
      if (fileImage == null) {
        debugPrint('Error: No file provided');
        return false;
      }
      await fileImage.copy(filePath);
      savefilePath = filePath;
      return true;
    } catch (e) {
      debugPrint('Error saving image: $e');
      return false;
    }
  }

  /// Saves an image file to the downloads folder for Android.
  ///
  /// Parameters:
  /// - [fileImage]: The image file to be saved.
  /// - [lengthFileName]: The length of the randomly generated file name (default is 5).
  /// - [fileName]: Optional custom file name.
  /// - [type]: The file extension/type (default is 'jpg').
  /// - [pathDirectory]: Optional custom download directory path.
  ///   [pathDirectory] : ExternalPath.DIRECTORY_MUSIC , ExternalPath.DIRECTORY_PODCASTS , ExternalPath.DIRECTORY_RINGTONES , ExternalPath.DIRECTORY_ALARMS , ExternalPath.DIRECTORY_NOTIFICATIONS
  ///   ExternalPath.DIRECTORY_PICTURES , ExternalPath.DIRECTORY_MOVIES , ExternalPath.DIRECTORY_DOWNLOADS , ExternalPath.DIRECTORY_DCIM , ExternalPath.DIRECTORY_DOCUMENTS
  ///   ExternalPath.DIRECTORY_SCREENSHOTS , ExternalPath.DIRECTORY_AUDIOBOOKS.
  /// Returns `true` if the file was saved successfully, otherwise `false`.

  static Future<bool> saveImageAndroid({
    required File? fileImage,
    int lengthFileName = 5,
    String? fileName,
    String? type = 'jpg',
    StorageDirectory? pathDirectory,
  }) async {
    final NativeAndroidPath nativeAndroidPath = NativeAndroidPath();
    String? directoryPath;
    String filePath = '';

    String localFileName =
        "image_${StringExtension.randomFileName(lengthFileName)}";

    String finalFilename = fileName ?? localFileName;

    try {
      if (!Platform.isAndroid) {
        throw Exception('Error saving : Unsupported platform');
      }

      if (Platform.isAndroid) {
        switch (pathDirectory) {
          case StorageDirectory.downloads:
            directoryPath = await nativeAndroidPath.getDownloadPath();
            break;
          case StorageDirectory.pictures:
            directoryPath = await nativeAndroidPath.getPicturesPath();
            break;
          case StorageDirectory.movies:
            directoryPath = await nativeAndroidPath.getMoviesPath();
            break;
          case StorageDirectory.dcim:
            directoryPath = await nativeAndroidPath.getDCIMPath();
            break;
          case StorageDirectory.documents:
            directoryPath = await nativeAndroidPath.getDocumentsPath();
            break;
          case StorageDirectory.music:
            directoryPath = await nativeAndroidPath.getMusicPath();
            break;
          default:
            directoryPath = await nativeAndroidPath.getDownloadPath();
        }

        if (directoryPath == null) {
          throw Exception('Error: Unable to get directory path');
        }

        filePath = '$directoryPath/$finalFilename.$type';
        debugPrint("path: $filePath");
        if (File(filePath).existsSync()) {
          filePath =
              '$directoryPath/$finalFilename${StringExtension.randomFileName(3)}.$type';
        }
      } else {
        throw Exception('Error saving: $e');
      }
      if (fileImage == null) {
        debugPrint('Error: No file provided');
        return false;
      }
      await fileImage.copy(filePath);
      savefilePath = filePath;
      return true;
    } catch (e) {
      debugPrint('Error saving: $e');
      return false;
    }
  }

  /// Saves an image file to the downloads folder for iOS.
  ///
  /// Parameters:
  /// - [fileImage]: The image file to be saved.
  /// - [lengthFileName]: The length of the randomly generated file name (default is 5).
  /// - [fileName]: Optional custom file name.
  /// - [type]: The file extension/type (default is 'jpg').
  /// - [pathDirectory]: Optional custom download directory path.
  ///   [pathDirectory] :
  ///   'DIRECTORY_DOWNLOADS' , 'DIRECTORY_MUSIC', 'DIRECTORY_PODCASTS' , 'DIRECTORY_RINGTONES' , 'DIRECTORY_ALARMS' , 'DIRECTORY_NOTIFICATIONS' , 'DIRECTORY_PICTURES' , 'DIRECTORY_MOVIES' , 'DIRECTORY_DCIM' , 'DIRECTORY_DOCUMENTS', 'DIRECTORY_SCREENSHOTS', 'DIRECTORY_AUDIOBOOKS'
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  static Future<bool> saveImageIos({
    required File? fileImage,
    int lengthFileName = 5,
    String? fileName,
    String? type = 'jpg',
    DirectoryType? pathDirectory,
  }) async {
    final externalPathIosMacPlugin = ExternalPathIosMac();
    String filePath = '';
    String localFileName =
        "image_${StringExtension.randomFileName(lengthFileName)}";

    String finalFilename = fileName ?? localFileName;

    try {
      if (Platform.isIOS) {
        var downloadDirectoryIos = await externalPathIosMacPlugin
            .getDirectoryPath(
              directory: pathDirectory ?? DirectoryType.downloads,
            );
        String downloadPath = downloadDirectoryIos.toString();
        debugPrint("downloadPath: $downloadPath");
        // 检查目录是否存在，如果不存在则创建
        Directory dir = Directory(downloadPath);
        if (!await dir.exists()) {
          await dir.create(recursive: true); // recursive: true 会创建所有父目录
          print('目录已创建: $downloadPath');
        }
        filePath = '$downloadPath/$finalFilename.$type';
        if (File(filePath).existsSync()) {
          filePath =
              '${downloadDirectoryIos.toString()}/$finalFilename${StringExtension.randomFileName(3)}.$type';
        }
        debugPrint("defaultPath: $filePath");
      } else {
        throw Exception('Error saving image: $e');
      }
      if (fileImage == null) {
        debugPrint('Error: No file provided');
        return false;
      }
      await fileImage.copy(filePath);
      savefilePath = filePath;
      return true;
    } catch (e) {
      debugPrint('Error saving image: $e');
      return false;
    }
  }

  /// Saves an image file to the downloads folder for Mac.
  ///
  /// Parameters:
  /// - [fileImage]: The image file to be saved.
  /// - [lengthFileName]: The length of the randomly generated file name (default is 5).
  /// - [fileName]: Optional custom file name.
  /// - [type]: The file extension/type (default is 'jpg').
  /// - [pathDirectory]: Optional custom download directory path.
  ///   [pathDirectory] : "MacDirectoryType.download" , "MacDirectoryType.pictures" , "MacDirectoryType.movies".
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  static Future<bool> saveImageMacOs({
    required File? fileImage,
    int lengthFileName = 5,
    String? fileName,
    String? type = 'jpg',
    MacDirectoryType? pathDirectory,
  }) async {
    final externalPathIosMacPlugin = ExternalPathIosMac();
    String filePath = '';
    String localFileName =
        "image_${StringExtension.randomFileName(lengthFileName)}";

    String finalFilename = fileName ?? localFileName;

    try {
      if (Platform.isMacOS) {
        var downloadDirectoryMac = await externalPathIosMacPlugin
            .getDirectoryPathMacOs(
              directory: pathDirectory ?? MacDirectoryType.downloads,
            );
        String downloadPath = downloadDirectoryMac.toString();
        debugPrint("downloadPath: $downloadPath");
        // 检查目录是否存在，如果不存在则创建
        Directory dir = Directory(downloadPath);
        if (!await dir.exists()) {
          await dir.create(recursive: true); // recursive: true 会创建所有父目录
          print('目录已创建: $downloadPath');
        }
        filePath = '$downloadPath/$finalFilename.$type';
        debugPrint("defaultPath: $filePath");
      } else {
        throw Exception('Error saving image: $e');
      }
      if (fileImage == null) {
        debugPrint('Error: No file provided');
        return false;
      }
      await fileImage.copy(filePath);
      savefilePath = filePath;
      return true;
    } catch (e) {
      debugPrint('Error saving image: $e');
      return false;
    }
  }

  /// Saves any file from a URL to the downloads folder for Windows or Web.
  ///
  /// Parameters:
  /// - [link]: The URL of the file to be downloaded.
  ///
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  ///
  static Future<bool> saveNetworkFileWindowsWeb({required String link}) async {
    File? filePath;
    Directory? downloadDirectory = await getDownloadsDirectory();
    try {
      var response = await http.get(Uri.parse(link));

      if (response.statusCode != 200) {
        throw Exception('Failed to load image: ${response.statusCode}');
      }

      String fileNameWithParams = path.basename(link);
      String fileName = fileNameWithParams.split('?')[0];
      String extension = path.extension(fileName);
      String baseName = path.basenameWithoutExtension(fileName);

      String? contentType = response.headers['content-type'];
      String fileExtension =
          fileExtensions[contentType] ??
          (extension.isNotEmpty ? extension : '.png');

      if (kIsWeb || Platform.isWindows) {
        filePath = File(
          path.join(downloadDirectory!.path, '$baseName$fileExtension'),
        );
        debugPrint("defaultPath: $filePath");
      } else {
        throw Exception('Platform not supported');
      }
      await filePath.writeAsBytes(response.bodyBytes);
      savefilePath = filePath.uri.toString();
      return true;
    } catch (e, stackTrace) {
      if (kDebugMode) {
        print('Error during image download: $e');
        print('Stack Trace: $stackTrace');
      }
      return false;
    }
  }

  /// Saves any file from a URL to the downloads folder for Android.
  ///
  /// Saves any file from a URL to the downloads folder for Android.
  ///
  /// Parameters:
  /// - [link]: The URL of the file to be downloaded.
  /// - [pathDirectory]: Optional custom download directory using StorageDirectory enum.
  ///   Options include: StorageDirectory.downloads, StorageDirectory.pictures,
  ///   StorageDirectory.movies, StorageDirectory.dim , StorageDirectory.documents,
  ///   StorageDirectory.music, etc.
  ///
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  static Future<bool> saveNetworkFileAndroid({
    required String link,
    StorageDirectory? pathDirectory,
  }) async {
    if (!Platform.isAndroid) {
      throw Exception('Error saving: Unsupported platform');
    }

    final NativeAndroidPath nativeAndroidPath = NativeAndroidPath();
    File? filePath;
    String? directoryPath;

    switch (pathDirectory) {
      case StorageDirectory.downloads:
        directoryPath = await nativeAndroidPath.getDownloadPath();
        break;
      case StorageDirectory.pictures:
        directoryPath = await nativeAndroidPath.getPicturesPath();
        break;
      case StorageDirectory.movies:
        directoryPath = await nativeAndroidPath.getMoviesPath();
        break;
      case StorageDirectory.dcim:
        directoryPath = await nativeAndroidPath.getDCIMPath();
        break;
      case StorageDirectory.documents:
        directoryPath = await nativeAndroidPath.getDocumentsPath();
        break;
      case StorageDirectory.music:
        directoryPath = await nativeAndroidPath.getMusicPath();
        break;
      default:
        directoryPath = await nativeAndroidPath.getDownloadPath();
    }

    if (directoryPath == null) {
      throw Exception('Error: Unable to get directory path');
    }

    try {
      var response = await http.get(Uri.parse(link));

      if (response.statusCode != 200) {
        throw Exception('Failed to load file: ${response.statusCode}');
      }

      String fileNameWithParams = path.basename(link);
      String fileName = fileNameWithParams.split('?')[0];
      String extension = path.extension(fileName);
      String baseName = path.basenameWithoutExtension(fileName);

      String? contentType = response.headers['content-type'];
      String fileExtension =
          fileExtensions[contentType] ??
          (extension.isNotEmpty ? extension : '.png');

      filePath = File(path.join(directoryPath, '$baseName$fileExtension'));

      if (await filePath.exists()) {
        filePath = File(
          path.join(
            directoryPath,
            '$baseName${StringExtension.randomFileName(3)}$fileExtension',
          ),
        );
        debugPrint("defaultPath: $filePath");
      }

      await filePath.writeAsBytes(response.bodyBytes);
      savefilePath = filePath.uri.toString();
      return true;
    } catch (e, stackTrace) {
      if (kDebugMode) {
        print('Error during file download: $e');
        print('Stack Trace: $stackTrace');
      }
      return false;
    }
  }

  /// Saves a file from a URL to a specified directory on iOS.
  ///
  /// Parameters:
  /// - [link]: The URL of the file to be downloaded.
  /// - [directoryType]: Optional custom download directory type from [ExternalPathIosMac.DirectoryType].
  ///   If not provided, defaults to [ExternalPathIosMac.DirectoryType.downloads].
  ///
  /// Returns:
  ///   `true` if the file was saved successfully, otherwise `false`.

  static Future<bool> saveNetworkFileIos({
    required String link,
    DirectoryType? directoryType,
  }) async {
    final externalPathIosMacPlugin = ExternalPathIosMac();
    File? filePath;

    try {
      var response = await http.get(Uri.parse(link));

      if (response.statusCode != 200) {
        throw Exception('Failed to load image: ${response.statusCode}');
      }

      String fileNameWithParams = path.basename(link);
      String fileName = fileNameWithParams.split('?')[0];
      String extension = path.extension(fileName);
      String baseName = path.basenameWithoutExtension(fileName);

      String? contentType = response.headers['content-type'];
      String fileExtension =
          fileExtensions[contentType] ??
          (extension.isNotEmpty ? extension : '.png');

      if (Platform.isIOS) {
        var downloadDirectoryIos = await externalPathIosMacPlugin
            .getDirectoryPath(
              directory: directoryType ?? DirectoryType.downloads,
            );

        String downloadPath = downloadDirectoryIos.toString();
        debugPrint("downloadPath: $downloadPath");
        // 检查目录是否存在，如果不存在则创建
        Directory dir = Directory(downloadPath);
        if (!await dir.exists()) {
          await dir.create(recursive: true); // recursive: true 会创建所有父目录
          debugPrint('目录已创建: $downloadPath');
        }

        filePath = File(path.join(downloadPath, '$baseName$fileExtension'));

        if (await filePath.exists()) {
          filePath = File(
            path.join(
              downloadPath,
              '$baseName${StringExtension.randomFileName(3)}$fileExtension',
            ),
          );
        }
      } else {
        throw Exception('Platform not supported');
      }
      debugPrint("defaultPath: $filePath");
      await filePath.writeAsBytes(response.bodyBytes);
      savefilePath = filePath.uri.toString();
      return true;
    } catch (e, stackTrace) {
      if (kDebugMode) {
        print('Error during image download: $e');
        print('Stack Trace: $stackTrace');
      }
      return false;
    }
  }

  /// Saves any file from a URL to the downloads folder for Mac.
  ///
  /// Parameters:
  /// - [link]: The URL of the file to be downloaded.
  /// - [pathDirectory]: Optional custom download directory path.
  ///   [pathDirectory] : "DIRECTORY_DOWNLOADS" , "DIRECTORY_PICTURES" , "DIRECTORY_MOVIES".
  /// Returns `true` if the file was saved successfully, otherwise `false`.
  static Future<bool> saveNetworkFileMac({
    required String link,
    MacDirectoryType? pathDirectory,
  }) async {
    final externalPathIosMacPlugin = ExternalPathIosMac();
    File? filePath;

    try {
      var response = await http.get(Uri.parse(link));

      if (response.statusCode != 200) {
        throw Exception('Failed to load image: ${response.statusCode}');
      }

      String fileNameWithParams = path.basename(link);
      String fileName = fileNameWithParams.split('?')[0];
      String extension = path.extension(fileName);
      String baseName = path.basenameWithoutExtension(fileName);

      String? contentType = response.headers['content-type'];
      String fileExtension =
          fileExtensions[contentType] ??
          (extension.isNotEmpty ? extension : '.png');

      if (Platform.isMacOS) {
        var downloadDirectoryMac = await externalPathIosMacPlugin
            .getDirectoryPathMacOs(
              directory: pathDirectory ?? MacDirectoryType.downloads,
            );
        String downloadPath = downloadDirectoryMac.toString();
        debugPrint("downloadPath: $downloadPath");
        // 检查目录是否存在，如果不存在则创建
        Directory dir = Directory(downloadPath);
        if (!await dir.exists()) {
          await dir.create(recursive: true); // recursive: true 会创建所有父目录
          print('目录已创建: $downloadPath');
        }
        filePath = File(path.join(downloadPath, '$baseName$fileExtension'));
        debugPrint("defaultPath: $filePath");
      } else {
        throw Exception('Platform not supported');
      }

      await filePath.writeAsBytes(response.bodyBytes);
      savefilePath = filePath.uri.toString();
      return true;
    } catch (e, stackTrace) {
      if (kDebugMode) {
        print('Error during image download: $e');
        print('Stack Trace: $stackTrace');
      }
      return false;
    }
  }

  static String? getSavePath() {
    var dupSavefilePath = savefilePath;
    savefilePath = null;
    return dupSavefilePath;
  }
}
